package com.example.gate.websocket;

import com.example.common.grpc.GrpcClientManager;
import com.example.game.CReq;
import com.example.game.CResp;
import com.example.common.constants.ServiceNames;
import com.example.common.grpc.DynamicGrpcClientManager;
import com.example.game.proto.internal.SrvReq;
import com.example.game.proto.internal.SrvResp;
import com.google.protobuf.ByteString;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * WebSocket消息处理器
 * 处理M0Base.proto协议的消息
 * 
 * @author: Allen
 * @create: 2025/1/27 14:30
 * @description: WebSocket消息处理器
 **/
@Slf4j
@Component
@ChannelHandler.Sharable
public class WebSocketMessageHandler extends SimpleChannelInboundHandler<CReq> {
    
    @Autowired
    private GrpcClientManager clientManager;
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, CReq request) throws Exception {
        try {
            // 解析CReq
            log.info("收到WebSocket请求: id={}, code={}, bodyLen={}",
                    request.getId(), request.getCode(), request.getBody().size());

            // 处理请求
            CResp response = processRequest(request);

            // 发送响应
            sendResponse(ctx, response);

            log.debug("发送WebSocket响应: id={}, code={}, ret={}",
                    response.getId(), response.getCode(), response.getRet());
            
        } catch (Exception e) {
            log.error("处理WebSocket消息失败", e);
            
            // 发送错误响应
            CResp errorResponse = CResp.newBuilder()
                    .setId(0)
                    .setCode(0)
                    .setRet(-1)
                    .setBody(ByteString.copyFromUtf8("处理消息失败: " + e.getMessage()))
                    .build();
            
            sendResponse(ctx, errorResponse);
        }
    }
    
    /**
     * 处理请求
     */
    private CResp processRequest(CReq request) {
        int id = request.getId();
        int code = request.getCode();
        ByteString body = request.getBody();
        
        try {
            // 根据协议号路由到不同的服务
            ServiceNames targetService = getTargetService(code);
            
            if (targetService == null) {
                return CResp.newBuilder()
                        .setId(id)
                        .setCode(code)
                        .setRet(-2) // 未知协议
                        .setBody(ByteString.copyFromUtf8("未知协议号: " + code))
                        .build();
            }
            
            // 构建内部gRPC请求
            SrvReq grpcRequest = SrvReq.newBuilder()
                    .setId(id)
                    .setCode(code)
                    .setSid(1001) // Gate服务器ID
                    .setUserId(0) // 暂时设为0，后续可以从session中获取
                    .setBody(body)
                    .build();
            
            // 调用目标服务
            SrvResp grpcResponse = callTargetService(targetService, grpcRequest);
            
            // 构建响应
            return CResp.newBuilder()
                    .setId(id)
                    .setCode(code)
                    .setRet(grpcResponse.getRet())
                    .setBody(grpcResponse.getBody())
                    .build();
            
        } catch (Exception e) {
            log.error("处理WebSocket请求异常: id={}, code={}", id, code, e);
            return CResp.newBuilder()
                    .setId(id)
                    .setCode(code)
                    .setRet(-1)
                    .setBody(ByteString.copyFromUtf8("服务器内部错误"))
                    .build();
        }
    }
    
    /**
     * 根据协议号获取目标服务
     */
    private ServiceNames getTargetService(int code) {
        // 根据协议号范围判断目标服务
        if (code >= 1000 && code < 2000) {
            return ServiceNames.LOBBY; // 用户相关协议
        } else if (code >= 2000 && code < 3000) {
            return ServiceNames.LOBBY; // 房间相关协议
        } else if (code >= 3000 && code < 4000) {
            return ServiceNames.GAME; // 游戏相关协议
        } else if (code >= 4000 && code < 5000) {
            return ServiceNames.GATE; // 网关相关协议
        } else {
            return null; // 未知协议
        }
    }
    
    /**
     * 调用目标服务
     */
    private SrvResp callTargetService(ServiceNames serviceType, SrvReq request) {
        try {
            return clientManager.callService(serviceType, request);
            
        } catch (Exception e) {
            log.error("调用{}服务失败", serviceType, e);
            return SrvResp.newBuilder()
                    .setId(request.getId())
                    .setRet(-1)
                    .setBody(ByteString.copyFromUtf8("调用服务失败: " + e.getMessage()))
                    .build();
        }
    }
    

    
    /**
     * 发送WebSocket响应
     */
    private void sendResponse(ChannelHandlerContext ctx, CResp response) {
        try {
            // 发送响应
            ctx.writeAndFlush(response);
            
        } catch (Exception e) {
            log.error("发送WebSocket响应失败", e);
        }
    }
    
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("WebSocket客户端连接: {}", ctx.channel().remoteAddress());
        super.channelActive(ctx);
    }
    
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("WebSocket客户端断开: {}", ctx.channel().remoteAddress());
        super.channelInactive(ctx);
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("WebSocket通道异常: {}", ctx.channel().remoteAddress(), cause);
        ctx.close();
    }
} 